package main

import (
	"fmt"
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/base"
	"github.com/alibaba/sentinel-golang/core/config"
	"github.com/alibaba/sentinel-golang/core/flow"
	"github.com/alibaba/sentinel-golang/logging"
	"log"
	"math/rand"
	"time"
)

func main() {
	// 定义三个变量，统计总共请求数，通过个数，失败个数
	var total, pass, block int

	// We should initialize Sentinel first.
	conf := config.NewDefaultConfig()
	// for testing, logging output to console
	conf.Sentinel.Log.Logger = logging.NewConsoleLogger()
	//方式一： 通过配置文件创建
	err := sentinel.InitWithConfig(conf)
	//方式二： 通过默认创建
	//err :sentinel.InitDefault()
	if err != nil {
		log.Fatal(err)
	}

	// TokenCalculateStrategy配置flow.WarmUp，
	//WarmUpPeriodSec配置10，
	//Threshold配置1000，
	//表示这1000个流量，要在10s内缓慢的增加到
	_, err = flow.LoadRules([]*flow.Rule{{
		Resource:               "lqz-test",  //资源名，即规则的作用目标
		TokenCalculateStrategy: flow.WarmUp, //使用WarmUp形式启动
		ControlBehavior:        flow.Reject, //表示流量控制器的控制策略；Reject表示超过阈值直接拒绝，Throttling表示匀速排队。 Threshold: 表示流控
		WarmUpPeriodSec:        10,          //预热的时间长度，该字段仅仅对 WarmUp 的TokenCalculateStrategy生效
		Threshold:              1000,        //表示流控阈值；如果字段 StatIntervalInMs 是1000(也就是1秒)，那么Threshold就表示QPS，流量控制器也就会依据资源的QPS来做流控
		//WarmUpColdFactor: 预热的因子，默认是3，该值的设置会影响预热的速度，该字段仅仅对 WarmUp 的TokenCalculateStrategy生效
	}})

	if err != nil {
		log.Fatalf("Unexpected error: %+v", err)
		return
	}

	ch := make(chan struct{})

	// 启动100个协程，分别：不停的请求
	for i := 0; i < 100; i++ {
		go func() {
			// 死循环
			for {
				total++
				e, b := sentinel.Entry("lqz-test", sentinel.WithTrafficType(base.Inbound))
				if b != nil {
					block++
				} else {
					pass++
					e.Exit()
				}
				time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond) // 每次随机睡10毫秒以内的时间
			}
		}()
	}

	go func() {
		// 统计过去一秒钟，总共多少个，通过多少个，block多少个
		var oldTotal, oldPass, oldBlock int
		for { //死循环每隔1s打印,上一秒中总共多少，通过多少，block多少
			oldSecondTotal := total - oldTotal
			oldTotal = total
			oldSecondPass := pass - oldPass
			oldPass = pass
			oldSecondBlock := block - oldBlock
			oldBlock = block
			time.Sleep(1 * time.Second)
			fmt.Printf("总共：%d,通过；%d,拒绝：%d \n", oldSecondTotal, oldSecondPass, oldSecondBlock)
		}
	}()

	<-ch
}
